#include <iostream>
#include <vector>
#include <unordered_map>
#include <cassert>
#include <cstring>
#include <thread>
#include <functional>
#include <memory>
#include <mutex>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/eventfd.h>
#include <sys/timerfd.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <condition_variable>

#define INF 0
#define DBG 1
#define ERR 2
#define LOG_LEVEL DBG

#define LOG(level, format, ...)                                                                                       \
    do                                                                                                                \
    {                                                                                                                 \
        if (level < LOG_LEVEL)                                                                                        \
            break;                                                                                                    \
        time_t t = time(NULL);                                                                                        \
        struct tm *ltm = localtime(&t);                                                                               \
        char tmp[32] = {0};                                                                                           \
        strftime(tmp, 31, "%H:%M:%S", ltm);                                                                           \
        fprintf(stdout, "[%p %s %s:%d]" format "\n", (void *)pthread_self(), tmp, __FILE__, __LINE__, ##__VA_ARGS__); \
    } while (0)
#define INF_LOG(format, ...) LOG(INF, format, ##__VA_ARGS__) // 使用不定参的...只能声明定义的时候用，使用的时候用__VA_ARGS__
#define DBG_LOG(format, ...) LOG(DBG, format, ##__VA_ARGS__)
#define ERR_LOG(format, ...) LOG(ERR, format, ##__VA_ARGS__)

#define BUFFER_DEFAULT_SIZE 1024
class Buffer
{
private:
    std::vector<char> _buffer;
    uint64_t _read_idx;  // 读偏移量
    uint64_t _write_idx; // 写偏移量
public:
    Buffer()
        : _buffer(BUFFER_DEFAULT_SIZE), _read_idx(0), _write_idx(0)
    {
    }
    // 获取起始地址
    char *Begin() const
    {
        return (char *)&_buffer[0];
    }
    // 获取当前写入位置地址
    char *WritePosition()
    {
        return Begin() + _write_idx;
    }
    // 获取当前读取位置
    char *ReadPosition()
    {
        return Begin() + _read_idx;
    }
    // 获取缓冲区末尾剩余空间大小 ---  写偏移之后空闲空间
    uint64_t TailIdeSize()
    {
        return _buffer.size() - _write_idx;
    }
    // 获取缓冲区头部剩余空间大小 --- 读偏移之前的空闲空间
    uint64_t HeadIdSize()
    {
        return _read_idx;
    }
    // 可读数据大小
    uint64_t ReadAbleSize()
    {
        return _write_idx - _read_idx;
    }
    // 移动读偏移量，移动的大小必须小于可读数据大小
    void MoveReadOffset(uint64_t len)
    {
        assert(len <= ReadAbleSize());
        _read_idx += len;
    }
    // 移动写偏移量,移动大小必须小于头部空闲空间和尾部空闲空间
    void MoveWriteOffset(uint64_t len)
    {
        assert(len <= (TailIdeSize() + HeadIdSize()));
        _write_idx += len;
    }
    // 确保可写空间足够（整体可写空间够，就移动数据，不够就扩容）
    void EnsureWriteSpace(uint64_t len)
    {
        if (TailIdeSize() > len) // 尾部空闲空间足够，直接返回
            return;
        // 尾部空闲空间不够，看尾部和头部空闲空间是否足够，够就移动数据
        if ((TailIdeSize() + HeadIdSize()) > len)
        {
            uint64_t rsz = ReadAbleSize();
            std::copy(ReadPosition(), ReadPosition() + rsz, Begin());
            _read_idx = 0;    // 读偏移量归0
            _write_idx = rsz; //  写偏移量为可读数据大小
        }
        else // 总体空间不够，扩容
        {
            _buffer.resize(_write_idx + len);
        }
    }
    /**
     * 写操作 写分三种数据类型： char* string   Buffer
    */

    // 写入数据
    void Write(const void *data, uint64_t len)
    {
        // 1. 保证有足够的空间 2. 把数据拷贝进去
        if (len == 0) // 防御性编程
            return;
        EnsureWriteSpace(len); // 确保可写空间
        std::copy((char *)data, (char *)data + len, WritePosition());
    }
    void WriteAndPush(const void *data, uint64_t len)
    {
        Write(data, len);
        MoveWriteOffset(len);
    }
    void WriteString(const std::string &data)
    {
        Write((const void *)data.c_str(), data.size());
    }
    void WriteStringAndPush(const std::string &data)
    {
        WriteString(data);
        MoveWriteOffset(data.size());
    }
    void WriteBuffer(Buffer &data)
    {
        Write((const void *)data.ReadPosition(), data.ReadAbleSize());
    }
    void WriteBufferAndPush(Buffer &data)
    {
        WriteBuffer(data);
        MoveWriteOffset(data.ReadAbleSize());
    }

    /**
     * 读操作：也分2种类型 Buffer  string  还有就是对HTTP协议的读取
    */

    // 读取数据
    void Read(void *buf, uint64_t len)
    {
        // 要求读取的数据必须小于可读数据
        assert(len <= ReadAbleSize());
        std::copy(ReadPosition(), ReadPosition() + len, (char *)buf);
    }
    void ReadAndPop(void *buf, uint64_t len)
    {
        Read(buf, len);
        MoveReadOffset(len);
    }
    std::string ReadAsString(uint64_t len)
    {
        assert(len <= ReadAbleSize());
        std::string str;
        str.resize(len);
        Read(&str[0], len);
        return str;
    }
    std::string ReadAsStringAndPop(uint64_t len)
    {
        std::string str = ReadAsString(len);
        MoveReadOffset(len);
        return str;
    }

    // 查找回车字符的地址
    char *FindCRLF()
    {
        char *res = (char *)memchr(ReadPosition(), '\n', ReadAbleSize());
        return res;
    }
    // 获取HTTP协议一行的数据
    std::string GetLine()
    {
        const char *pos = FindCRLF();
        if (pos == NULL)
            return "";
        return ReadAsString(pos - ReadPosition() + 1); // 把\n也读取进去 -- 方便
    }
    std::string GetLineAndPop()
    {
        std::string str = GetLine();
        MoveReadOffset(str.size());
        return str;
    }

    // 清空缓冲区
    void Clear()
    {
        _read_idx = 0;
        _write_idx = 0;
    }
};

#define MAX_LISTEN 1024
class Socket
{
private:
    int _sockfd;

public:
    Socket()
        : _sockfd(-1)
    {
    }
    Socket(int fd)
        : _sockfd(fd)
    {
    }
    ~Socket()
    {
        Close();
    }
    int Fd()
    {
        return _sockfd;
    }
    void Close()
    {
        if (_sockfd != -1)
            close(_sockfd);
        _sockfd = -1;
    }
    // 创建套接字
    bool Create()
    {
        int ret = socket(AF_INET, SOCK_STREAM, 0);
        if (ret < 0)
        {
            ERR_LOG("CREATE SOCKET FAILED:%s", strerror(errno));
            return false;
        }
        _sockfd = ret;
        return true;
    }
    // 绑定地址信息
    bool Bind(const std::string &ip, uint16_t port)
    {
        struct sockaddr_in addr;
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        int ret = bind(_sockfd, (const sockaddr *)&addr, sizeof(addr));
        if (ret < 0)
        {
            ERR_LOG("BIND SOCKET FAILED:%s", strerror(errno));
            return false;
        }
        return true;
    }
    // 监听
    bool Listen(int backlog = MAX_LISTEN)
    {
        // backlog 影响全连接队列的长度 是listen 的第二个参数 + 1.
        // 全连接队列（accpetd队列）（用来保存处于established状态，但是应用层没有调用accept取走的请求）
        int ret = listen(_sockfd, backlog);
        if (ret < 0)
        {
            ERR_LOG("LISTENT SOCKET FAILED:%s", strerror(errno));
            return false;
        }
        return true;
    }
    // 像服务器发起链接
    bool Connect(const std::string &ip, uint16_t port)
    {
        struct sockaddr_in addr;
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        int ret = connect(_sockfd, (const sockaddr *)&addr, sizeof(addr));
        if (ret < 0)
        {
            ERR_LOG("CONNECT SERVER FAILED", strerror(errno));
            return false;
        }
        return true;
    }
    // 获取新链接
    int Accept()
    {
        int newfd = accept(_sockfd, NULL, NULL);
        if (newfd < 0)
        {
            ERR_LOG("ACCEPT SOCKET FAILED:%s", strerror(errno));
            return -1;
        }
        return newfd;
    }
    // 接收数据
    ssize_t Recv(void *buffer, size_t len, int flag = 0) // flag=0 默认阻塞
    {
        int n = recv(_sockfd, buffer, len, flag);
        if (n == 0)
        {
            // 等于0表示连接断开了
            DBG_LOG("CONNECTION CLOSED");
            return -1;
        }
        if (n < 0) //小于0的时候表示读出错了
        {
            if (errno == EAGAIN || errno == EINTR)
            {
                //EAGAIN    表示当前socket的接收缓冲区中没有数据，在非阻塞情况下才会出现这种错误
                //EINTR     表示当前socket的阻塞等待被信号打断了
                return 0; //表示这次没有接收到数据
            }
            ERR_LOG("SOCKET RECV FAILED");
            return -1;
        }
        return n;
    }
    // 非阻塞式接收
    ssize_t NonBlockRecv(void *buffer, size_t len)
    {
        return Recv(buffer, len, MSG_DONTWAIT);
    }

    // 发送数据 -- 外部可以根据实际发送的数据长度来进行下一步处理
    ssize_t Send(const void *buffer, size_t len, int flag = 0)
    {
        int n = send(_sockfd, buffer, len, flag);
        if (n < 0)
        {
            if (errno == EAGAIN || errno == EINTR)
                return 0;
            ERR_LOG("SOCKET SEND FAILED");
            return -1;
        }
        return n;
    }
    //非阻塞发送数据
    ssize_t NonBlockSend(void *buf, size_t len)
    {
        return send(_sockfd, buf, len, MSG_DONTWAIT);
    }
    // 创建一个服务器连接
    bool CreateServer(uint16_t port, const std::string &ip = "0.0.0.0", bool block_flag = false)
    {
        // 创建套接字
        if (Create() == false)
            return false;
        if (block_flag == true)
            NonBlock();
        // 设置端口复用
        ReuseAddress();
        // 绑定地址
        if (Bind(ip, port) == false)
            return false;
        // 开始监听
        if (Listen() == false)
            return false;
        return true;
    }
    // 创建一个客服端连接
    bool CreateClient(uint16_t port, const std::string ip)
    {
        // 创建套接字
        if (Create() == false)
            return false;
        if (Connect(ip, port) == false)
            return false;
        return true;
    }

    /*
        一个连接绑定了地址和端口之后一旦主动关闭连接的一方最终会进入time_wait状态，这时候套接字
        并不会立即被释放，因此IP地址和端口依然被占用，导致我们无法立即去使用它，在服务器使用的时候，
        崩溃了，退出了，会无法立即重启，所以我们要开启地址重用。
    */
    //设置套接字选项 -- 开启端口复用
    void ReuseAddress()
    {
        int val = 1;
        setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT | SO_REUSEADDR, &val, sizeof(val));
        val = 1;
        setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT, (void *)&val, sizeof(int));
    }
    /*
        我们在使用套接字去接收数据的时候，一次性可能取不完数据，就需要循环去接收缓冲区里的数据，什么时候取完呢？
        就是取到没有数据为止，但是套接字默认是阻塞的，没有数据的时候再去取就会被阻塞住，程序就
        无法继续往下走了，所以我们需要将套接字设置为非阻塞
    */
    //设置套接字阻塞属性 -- 设置为非阻塞
    void NonBlock()
    {
        int flag = fcntl(_sockfd, F_GETFL, 0);
        fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK);
    }
};

class EventLoop;
class Channel
{
private:
    EventLoop *_loop;
    int _fd;
    uint32_t _events;  // 当前需要监控的事件
    uint32_t _revents; // 当前连接触发的事件
    using EventCallback = std::function<void()>;

    /*
        只有我们的连接才知道，一旦事件触发了该去怎么处理，所以需要设置回调函数。
        当启动读事件监控，就需要将channel挂到EventLoop上面进行事件监控，
        当可读事件触发，就会调用channel里设置的回调函数。
    */
    EventCallback _read_callback;  //可读事件被触发的回调函数
    EventCallback _write_callback; //可写事件被触发的回调函数
    EventCallback _error_callback; //错误事件被触发的回调函数
    EventCallback _close_callback; //连接断开事件被触发的回调函数
    EventCallback _event_callback; //任意事件被触发的回调函数

public:
    Channel(EventLoop *loop, int fd)
        : _loop(loop), _fd(fd), _events(0), _revents(0)
    {
    }
    int Fd()
    {
        return _fd;
    }
    uint32_t Events()
    {
        return _events;
    }
    // 设置已就绪事件
    void SetREvents(uint32_t events)
    {
        _revents = events;
    }

    void SetReadCallback(const EventCallback &cb)
    {
        _read_callback = cb;
    }
    void SetWriteCallback(const EventCallback &cb)
    {
        _write_callback = cb;
    }
    void SetErrorCallback(const EventCallback &cb)
    {
        _error_callback = cb;
    }
    void SetCloseCallback(const EventCallback &cb)
    {
        _close_callback = cb;
    }
    void SetEventCallback(const EventCallback &cb)
    {
        _event_callback = cb;
    }

    // 当前是否监控了可读
    bool ReadAble()
    {
        return (_events & EPOLLIN);
    }
    // 当前是否监控可写
    bool WriteAble()
    {
        return (_events & EPOLLOUT);
    }
    //启动可写事件监控
    void EnableWrite()
    {
        _events |= EPOLLOUT;
        Update();
    }
    // 启动可读事件监控
    void EnableRead()
    {
        _events |= EPOLLIN;
        Update();
    }
    //关闭读事件监控
    void DisableRead()
    {
        _events &= ~EPOLLIN;
        Update();
    }
    //关闭写事件监控
    void DisableWrite()
    {
        _events &= ~EPOLLOUT;
        Update();
    }
    //关闭所有事件监控
    void DisableAll()
    {
        _events &= 0;
    }
    /*
        关闭事件监控，只是不去关心这个事件了，但还是在EventLoop中。
        移除事件监控，才是真正的将它从EventLoop中移除
    */
    //移除监控
    void Remove();
    void Update();
    /*
        EventLoop不管你触发了什么事件我就去调用对应的回调函数，EventLoop不用管。
        EventLoop只管你触发了事件，我就调用你的HandleEvent，你自己来决定什么样的事件该如何处理
        这是最能体现Channel模块作用的功能之一
    */
    //事件处理，一旦连接触发了事件，就调用这个函数，自己触发了什么事件如何处理自己决定
    void HandleEvent()
    {
        // EPOLLIN: 可读  EPOLLOUT：可写  EPOLLRDHUP：对端关闭连接或半关闭  EPOLLPRI：有紧急数据可读 EPOLLERR：文件描述符发生错误
        // EPOLLHUP: 挂断事件（连接完全关闭，需清理资源）
        if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
        {
            if (_event_callback)
                _event_callback();
            if (_read_callback)
                _read_callback();
        }
        // 有可能会释放连接的操作事件，一次只处理一个
        if (_revents & EPOLLOUT)
        {
            if (_event_callback)
                _event_callback();
            if (_write_callback)
                _write_callback();
        }
        else if (_revents & EPOLLERR)
        {
            if (_event_callback)
                _event_callback();
            if (_error_callback)
                _error_callback();
        }
        else if (_revents & EPOLLHUP)
        {
            if (_event_callback)
                _event_callback();
            if (_close_callback)
                _close_callback();
        }
    }
};

#define MAX_EPOLLEVENTS 1024
class Poller
{
private:
    int _epfd;
    struct epoll_event _evs[MAX_EPOLLEVENTS];     // 存储从 epoll_wait 返回的就绪事件 的结构体数组
    std::unordered_map<int, Channel *> _channels; // 文件描述符和其对应的channel对象的关联关系
private:
    // 对epoll的直接操作
    void Update(Channel *channel, int op)
    {
        int fd = channel->Fd();
        struct epoll_event ev;
        ev.data.fd = fd;
        ev.events = channel->Events();
        int ret = epoll_ctl(_epfd, op, fd, &ev); // 用户告诉内核关心哪些文件描述符上的哪些事件
        if (ret < 0)
        {
            ERR_LOG("EPOLL_CTL FAILED");
        }
        return;
    }
    // 判断一个Channel是否已经添加了事件监控（是否在hash中管理）
    bool HasChannel(Channel *channel)
    {
        auto pos = _channels.find(channel->Fd());
        if (pos == _channels.end())
        {
            return false;
        }
        return true;
    }

public:
    Poller()
    {
        _epfd = epoll_create(MAX_EPOLLEVENTS);
        if (_epfd == -1)
        {
            ERR_LOG("EPOLL CREATE FALED");
            abort();
        }
    }
    // 添加或者修改监控事件
    void UpdateEvent(Channel *channel)
    {
        bool ret = HasChannel(channel);
        if (ret == false)
        {
            _channels.insert(std::make_pair(channel->Fd(), channel));
            return Update(channel, EPOLL_CTL_ADD);
        }
        return Update(channel, EPOLL_CTL_MOD);
    }
    // 移除监控
    void RemoveEvent(Channel *channel)
    {
        bool ret = HasChannel(channel);
        if (ret == false)
            return;
        _channels.erase(channel->Fd());
        return Update(channel, EPOLL_CTL_DEL);
    }
    // 开始监控，返回活跃连接
    void Poll(std::vector<Channel *> *active)
    {
        //  <0：阻塞等待
        int n = epoll_wait(_epfd, _evs, MAX_EPOLLEVENTS, -1);
        if (n < 0)
        {
            if (errno == EINTR) // 被信号打断
            {
                return;
            }
            ERR_LOG("EPOLL_WAIT FAILED:%s", strerror(errno));
            abort();
        }
        for (int i = 0; i < n; i++)
        {
            auto it = _channels.find(_evs[i].data.fd);
            assert(it != _channels.end());
            it->second->SetREvents(_evs[i].events); // 设置实际就绪的事件
            active->push_back(it->second);
        }
    }
};

using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
// 定时器任务类
class TimerTask
{
private:
    uint64_t _id;      // 定时器任务对象ID  定时任务必须得找得着，一个程序里定时任务可能有很多
    uint32_t _timeout; // 定时任务的超时时间
    bool _canceled;    // true --- 定时任务被取消   false -- 不取消
    TaskFunc _task_cb; // 定时器要执行的定时任务

    /*
    用于删除TimerWheel中保存的定时器任务对象信息，定时任务释放的时候也要清理TimerWheel中保存的定时器对象信息
    为什么将这个_release设置到TimerTask里面呢，不在TimerWheel层管理？
    因为这个TimerWheel不知道是否某个定时任务真的释放了，而TimerTask是最清楚的，自己真的释放了就会调用析构函数
    */

    ReleaseFunc _release; // 用于删除TimeWhile中保存的定时器任务对象信息（删除unordered_ma中的元素）
public:
    TimerTask(uint64_t id, uint32_t delay, const TaskFunc &cb)
        : _id(id),
          _timeout(delay),
          _canceled(false),
          _task_cb(cb)
    {
    }
    ~TimerTask()
    {
        if (_canceled == false) // 定时任务没有被取消
            _task_cb();
        _release();
    }
    void SetRelease(const ReleaseFunc &cb)
    {
        _release = cb;
    }
    uint32_t DelayTime()
    {
        return _timeout;
    }
    void Cancel()
    {
        _canceled = true;
    }
};

// 时间轮类
class TimerWheel
{
private:
    using WeakTask = std::weak_ptr<TimerTask>;
    using PtrTask = std::shared_ptr<TimerTask>;
    int _tick;     // 当前的秒针，走到哪里释放到哪里，就相当于执行哪里的任务
    int _capacity; // 表盘最大数量，其实就是最大延迟时间
    std::vector<std::vector<PtrTask>> _wheel;
    std::unordered_map<uint64_t, WeakTask> _timers;
    EventLoop *_loop;
    int _timerfd; // 定时器描述符 --- 可读事件回调就是读取定时器，执行定时任务
    std::unique_ptr<Channel> _timer_channel;

public:
    TimerWheel(EventLoop *loop)
        : _tick(0), _capacity(60), _wheel(_capacity),
          _loop(loop),
          _timerfd(CreateTimerFd()),
          _timer_channel(new Channel(loop, _timerfd))
    {
        _timer_channel->SetReadCallback(std::bind(&TimerWheel::OnTime, this));
        _timer_channel->EnableRead();
    }

public:
    void RemoveTimer(uint64_t id)
    {
        auto pos = _timers.find(id);
        if (pos != _timers.end())
            _timers.erase(pos);
    }
    static int CreateTimerFd()
    {
        //
        int timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
        if (timerfd < 0)
        {
            ERR_LOG("TIMERFD CREATE FAILED");
            abort();
        }

        struct itimerspec itime;
        // 第一次超时时间为1s后
        itime.it_value.tv_sec = 1;
        itime.it_value.tv_nsec = 0;

        // 第一次超时后，每次超时的间隔时间为1s
        itime.it_interval.tv_sec = 1;
        itime.it_interval.tv_nsec = 0;

        timerfd_settime(timerfd, 0, &itime, nullptr);

        return timerfd;
    }

    int ReadTimeFd()
    {
        uint64_t times;
        int ret = read(_timerfd, &times, 8); // read读取到的数据times就是从上一次read之后超时的次数
        if (ret < 0)
        {
            ERR_LOG("READ TIMERFD FAILED");
            abort();
        }
        return times;
    }
    // 时间轮定时任务执行函数(该函数每秒执行一次)
    void RunTimerTask()
    {
        _tick = (_tick + 1) % _capacity;
        _wheel[_tick].clear(); // 情况指定位置的数组，就会把数组中保存的所有管理定时器对象的shared_ptr释放掉
    }

    // 这个函数每秒钟都会被执行一次，相当于秒针向后走了一步
    void OnTime()
    {
        // 根据实际的超时次数来执行对应的超时任务
        int times = ReadTimeFd();
        for (int i = 0; i < times; i++)
        {
            RunTimerTask();
        }
    }
    // 添加定时任务
    void TimerAddInLoop(uint64_t id, uint32_t delay, const TaskFunc &cb)
    {
        // 1. 构建定时任务
        PtrTask pt(new TimerTask(id, delay, cb)); // PtrTask 引用计数 = 1    这里出了作用域，那么PtrTask的引用计数就为1了。那么最后RunTimerTask执行clear的之后，就直接析构任务了
        pt->SetRelease(std::bind(&TimerWheel::RemoveTimer, this, id));
        // 2. 将定时任务加入到——wheel中
        int i = (_tick + delay) % _capacity;
        _wheel[i].push_back(pt); //  PtrTask引用计数 = 2
        //3. 加入到时间轮的_timers里面
        auto pos = _timers.find(id);
        if (pos == _timers.end())
        {
            _timers.insert({id, pt});
        }
    }
    // 刷新/延迟定时任务
    void TimerRefreshInLoop(uint64_t id)
    {
        //通过定时器对象的weak_ptr构造一个shared_ptr，再添加到时间轮中
        auto it = _timers.find(id);
        if (it == _timers.end())
            return;
        PtrTask pt = it->second.lock();
        // 将对应的pt加入到_wheel中
        int delay = pt->DelayTime();
        int i = (_tick + delay) % _capacity;
        _wheel[i].push_back(pt);
    }

    void TimerCancelInLoop(uint64_t id)
    {
        auto pos = _timers.find(id);
        if (pos == _timers.end()) // 没有找到定时任务，无法刷新，无法延时
            return;
        PtrTask pt = pos->second.lock();
        if (pt) // 如果自己已经销毁，则可能为空
            pt->Cancel();
    }
    //定时器中有个_timers成员，定时器信息的操作有可能在多线程中进行(如主线程想添加给所有的连接添加一个定时任务)，因此需要考虑线程安全问题
    //如果不想加锁，那就把对应定期的所有操作，都放到一个线程中进行
    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb); // 因为用到了EventLoop的_loop成员，所以要在EventLoop代码后面去实现
    void TimerRefresh(uint64_t id);
    void TimerCancel(uint64_t id);
    bool HasTimer(uint64_t id)
    {
        auto it = _timers.find(id);
        if (it == _timers.end())
        {
            return false;
        }
        return true;
    }
};

class EventLoop
{
private:
    using Functor = std::function<void()>;
    std::thread::id _thread_id;              // 线程ID
    int _eventfd;                            // 用于唤醒IO事件监控可能导致阻塞
    std::unique_ptr<Channel> _event_channel; //为了能更好的管理_event_fd，为其创建一个channel
    Poller _poller;                          // 用于进行所有文件描述符的事件监控
    std::vector<Functor> _tasks;             // 任务池
    std::mutex _mutex;                       // 保证多线程对任务池进行操作的线程安全
    TimerWheel _timer_wheel;

public:
    // 执行任务池中的所有任务
    void RunAllTask()
    {
        // 细节：为什么要交换任务而不直接操作_tasks？？
        // 锁的粒度控制：通过交换，锁的持有时间仅覆盖 交换操作本身，而不是整个任务执行过程。 后续遍历 functor 执行任务时不再需要锁，避免阻塞其他线程向 _tasks 添加新任务。
        //线程安全：其他线程调用 QueueInLoop 时，可以向新的空 _tasks 添加任务，而当前线程处理的是交换出的旧任务集合。 避免遍历 _tasks 时被其他线程修改导致竞态条件。
        std::vector<Functor> functor;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            functor.swap(_tasks);
        }
        for (auto f : functor)
        {
            f();
        }
    }
    static int CreateEventFd()
    {
        // int eventfd(unsigned int initval, int flags);   unsigned: 初始值
        int efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
        if (efd < 0)
        {
            perror("EVENTFD FAILED");
            abort();
        }
        return efd;
    }

    // 读取 事件管理文件描述符
    void ReadEvent()
    {
        uint64_t res = 0;
        int ret = read(_eventfd, &res, sizeof(res));
        if (ret < 0)
        {
            //EINTR -- 被信号打断    EAGAIN -- 暂时无数据可读（非阻塞时才会触发）
            if (errno == EINTR || errno == EAGAIN)
            {
                return;
            }
            ERR_LOG("READ EVENTFD FAILED");
            abort();
        }
    }

    // 向_eventfd中写入数据，唤醒IO事件
    void WeakUpEventFd()
    {
        uint64_t val = 1;
        int ret = write(_eventfd, &val, sizeof(val));
        if (ret < 0)
        {
            if (errno == EINTR)
            {
                return;
            }
            ERR_LOG("WRITE EVENTFD FAILED");
            abort();
        }
    }

public:
    EventLoop()
        : _thread_id(std::this_thread::get_id()), // //获取的是当前实例化该EventLoop线程的id，进行线程绑定
          _eventfd(CreateEventFd()),
          _event_channel(new Channel(this, _eventfd)),
          _timer_wheel(this)
    {
        // 给_eventfd添加可读事件回调，读取eventfd事件通知次数
        _event_channel->SetReadCallback(std::bind(&EventLoop::ReadEvent, this));
        // 启动eventfd的读事件监控
        _event_channel->EnableRead();
    }
    // 判断要执行的任务是否处于线程当中，如果是则执行，不是则压入队列
    void RunInLoop(const Functor &cb)
    {
        if (IsInLoop())
        {
            return cb();
        }
        return QueueInLoop(cb);
    }
    //将操作压入任务池
    void QueueInLoop(const Functor &cb)
    {
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _tasks.push_back(cb);
        }
        // 其他线程把任务投入到你的EventLoop的任务池里面了，需要执行任务池里的这个任务
        // 所以需要唤醒这个线程（因为这个线程可能在等待事件就绪的阻塞状态）
        WeakUpEventFd();
    }
    // 判断当前线程是否是EventLoop对应的线程
    bool IsInLoop()
    {
        return _thread_id == std::this_thread::get_id();
    }
    // 添加/修改描述符事件监控
    void UpdateEvent(Channel *channel)
    {
        _poller.UpdateEvent(channel);
    }
    // 移除描述符事件监控
    void RemoveEvent(Channel *channel)
    {
        _poller.RemoveEvent(channel);
    }
    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb)
    {
        return _timer_wheel.TimerAdd(id, delay, cb);
    }
    void TimerRefresh(uint64_t id)
    {
        return _timer_wheel.TimerRefresh(id);
    }
    void TimerCancel(uint64_t id)
    {
        return _timer_wheel.TimerCancel(id);
    }
    bool HasTimer(uint64_t id)
    {
        return _timer_wheel.HasTimer(id);
    }
    //三步走--事件监控-》就绪事件处理-》执行任务
    void Start()
    {
        while (1)
        {
            // 事件监控
            std::vector<Channel *> actives;
            _poller.Poll(&actives);
            // 就绪事件处理
            for (auto &channel : actives)
            {
                channel->HandleEvent();
            }
            // 执行任务池中的所有任务
            RunAllTask();
        }
    }
};

class LoopThread
{
private:
    // 主要为了实现同步，避免新线程还没有来得及实例化_loop的时候，主线程就要获取对应的EventLoop
    std::mutex _mutex;
    std::condition_variable _cond; // 条件变量
    EventLoop *_loop;
    std::thread _thread; // EventLoop对应的线程
private:
    // 实例化EventLoop对象，并且开始运行EventLoop模块的功能
    void ThreadEntry()
    {
        EventLoop loop; //因为下面Start会一直循环运行，所以EventLoop的生命周期不会结束
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _loop = &loop;
            _cond.notify_all();
        }
        loop.Start();
    }

public:
    LoopThread()
        : _loop(nullptr),
          _thread(std::thread(&LoopThread::ThreadEntry, this)) // 创建线程，设定线程入口函数
    {
    }
    // 返回当前线程关联的EventLoop对象指针
    EventLoop *GetLoop()
    {
        EventLoop *loop = nullptr;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            //第二个参数时一个bool的函数，如果为false就一直阻塞住，被唤醒才能继续往下走
            _cond.wait(lock, [&]() {
                return _loop != nullptr;
            });
            loop = _loop;
        }
        return loop;
    }
};

class LoopThreadPool
{
private:
    int _thread_count;                  // 从属线程的数量
    int _next_idx;                      //
    EventLoop *_baseLoop;               // 主EventLoop，运行在主线程，从属线程数量为0，则所有操作都在baseLoop中进行
    std::vector<LoopThread *> _threads; // 保存所有的LoopThread对象
    std::vector<EventLoop *> _loops;    // 从属线程数量大于0则从_loops中进行线程EventLoop分配
public:
    LoopThreadPool(EventLoop *baseLoop)
        : _thread_count(0),
          _next_idx(0),
          _baseLoop(baseLoop)
    {
    }
    // 设置线程数量
    void SetThreadCount(int count)
    {
        _thread_count = count;
    }
    // 创建所有的从属线程
    void Create()
    {
        if (_thread_count > 0)
        {
            _threads.resize(_thread_count);
            _loops.resize(_thread_count);
            for (int i = 0; i < _thread_count; ++i)
            {
                _threads[i] = new LoopThread;
                _loops[i] = _threads[i]->GetLoop();
            }
        }
    }
    //为了实现RR轮转，返回下一个从属线程的EventLoop
    EventLoop *NextLoop()
    {
        if (_thread_count == 0)
            return _baseLoop;
        _next_idx = (_next_idx + 1) % _thread_count;
        return _loops[_next_idx];
    }
};

class Any
{
public:
    class holder
    {
    public:
        virtual ~holder() {}
        virtual const std::type_info &type() = 0; // 获取当前子类的数据类型 -- 返回类型是const type_info&
        virtual holder *clone() = 0;              //针对当前的对象自身，克隆出一个新的子类对象
    };
    template <class T>
    class placeholder : public holder
    {
    public:
        placeholder(const T &val = T()) : _val(val) {}
        virtual const std::type_info &type()
        {
            return typeid(T);
        }
        virtual holder *clone()
        {
            return new placeholder(_val);
        }
        T _val; //主要是这里，如果不通过virtual，则无法释放这里的对象
    };

    Any() : _content(NULL)
    {
    }
    template <class T>
    Any(const T &content) : _content(new placeholder<T>(content))
    {
    }
    Any(const Any &other)
        : _content(other._content ? other._content->clone() : NULL)
    {
    }
    ~Any()
    {
        delete _content;
    }
    Any &swap(Any &other)
    {
        std::swap(_content, other._content);
        return *this;
    }
    template <class T>
    Any &operator=(const T &val)
    {
        Any(val).swap(*this); //这样写的好处：Any(val)为临时对象，交换完生命周期就到了，就会调用自己的析构函数
        return *this;
    }
    Any &operator=(const Any &other)
    {
        Any(other).swap(*this);
        return *this;
    }

    template <class T>
    T *get() //返回子类对象保存数据的指针
    {
        if (typeid(T) != _content->type()) //如果你要的类型和我保存的类型不匹配
            return NULL;
        return &(((placeholder<T> *)_content)->_val);
    }

public:
    holder *_content;
};

typedef enum
{
    DISCONNECTED, // 连接关闭状态
    CONNECTING,   // 连接建立成功 - 待处理状态
    CONNECTED,    // 连接建立完成，各种设置已经完成，可以通信的状态(三次握手完成，连接已建立。)
    DISCONNECTING // 待关闭状态
} ConnStatus;

class Connection;
using PtrConnection = std::shared_ptr<Connection>;
class Connection : public std::enable_shared_from_this<Connection>
{
private:
    uint64_t _conn_id;             // 连接的唯一ID，也是定时任务唯一ID，便于连接的管理和查找
    int _sockfd;                   // 连接关联的文件描述符
    bool _enable_inactive_release; // 连接是否启动非活跃销毁的判断标致，默认false
    EventLoop *_loop;              // 连接所关联的一个EventLoop
    ConnStatus _statu;             // 连接状态
    Socket _socket;                // 套接字管理操作
    Channel _channel;              // 连接的事件管理
    Buffer _in_buffer;             // 输入缓冲区 -- 存放从sock中读取到的数据
    Buffer _out_buffer;            // 输出缓冲区 -- 存放要发送给对端的数据
    Any _context;                  // 请求的接收处理上下文

    // 下面这四个回调函数，是让server模块来设置的（服务器模块的处理回调是组件使用者设置的）
    using ConnectedCallback = std::function<void(const PtrConnection &)>;
    using MessageCallback = std::function<void(const PtrConnection &, Buffer *)>;
    using ClosedCallback = std::function<void(const PtrConnection &)>;
    using AnyEventCallback = std::function<void(const PtrConnection &)>;

    ConnectedCallback _connected_callback;
    MessageCallback _message_callback;
    ClosedCallback _closed_callback;
    AnyEventCallback _event_callback;
    // 组件内的连接关闭回调 -- 组件内设置的，因为服务器组件内会把所有的连接管理起来。
    // 一旦某个连接要关闭，就应该从管理的地方移除掉自己的信息。
    ClosedCallback _server_closed_callback;

private:
    //五个channel的事件回调函数
    // 描述符可读事件触发后调用的函数，接收socket数据放到接受缓冲区中，然后调用_message_callback
    void HandleRead()
    {
        char buf[65536];
        ssize_t ret = _socket.NonBlockRecv(buf, 65535);
        if (ret < 0)
        {
            // 读取出错了，可能是客户端关闭，不能直接关闭连接，因为可能有数据没发送或者有数据还没有处理
            return ShutdownInLoop();
        }
        else if (ret == 0)
        {
            //表示没有读取到数据，并不是连接断开，因为我们调用的是自己封装的NonBlockRecv
            return;
        }
        _in_buffer.WriteAndPush(buf, ret);
        // 2. 调用message_callback进行业务处理
        if (_in_buffer.ReadAbleSize() > 0)
        {
            //shared_from_this -- 从当前对象自身获取自身的shared_ptr管理对象
            _message_callback(shared_from_this(), &_in_buffer);
        }
    }
    // 描述符触发可写事件后调用的函数，将发送缓冲区中的数据进行发送
    void HandleWrite()
    {
        ssize_t ret = _socket.NonBlockSend(_out_buffer.ReadPosition(), _out_buffer.ReadAbleSize());
        if (ret < 0)
        {
            // 发送错误，关闭连接
            if (_in_buffer.ReadAbleSize() > 0) // 接收缓冲区还有数据，得处理了
            {
                _message_callback(shared_from_this(), &_in_buffer);
            }
            return Release(); // 真正的释放连接
        }
        _out_buffer.MoveReadOffset(ret);
        if (_out_buffer.ReadAbleSize() == 0)
        {
            _channel.DisableWrite(); // 数据发送完成了，就关闭写事件监控
            //如果当前是连接待关闭状态，并且数据发送完了，则可以将连接直接释放
            if (_statu == DISCONNECTING)
                return Release();
        }
        // 发送数据可能没有发送完，不关闭写事件监控
        return;
    }
    //描述符触发挂断事件
    void HandleClose()
    {
        /*一旦连接挂断了，套接字就什么都干不了了，因此有数据待处理就处理一下，完毕关闭连接*/
        if (_in_buffer.ReadAbleSize() > 0)
        {
            _message_callback(shared_from_this(), &_in_buffer);
        }
        return Release();
    }
    // 描述符触发出错事件
    void HandleError()
    {
        return HandleClose();
    }
    // 描述符触发任意事件
    void HandleEvent()
    {
        // 刷新连接活跃度
        if (_enable_inactive_release == true)
        {
            _loop->TimerRefresh(_conn_id);
        }
        // 调用组件使用者的任意事件回调
        if (_event_callback)
            _event_callback(shared_from_this());
    }
    // 新连接获取之后，所处的状态下要进行各种设置
    void EstablishedInLoop()
    {
        // // 1. 修改连接状态；  2. 启动读事件监控；  3. 调用回调函数
        assert(_statu == CONNECTING); //当前的状态必须一定是上层的半连接状态
        _statu = CONNECTED;           //当前函数执行完毕，则连接进入已完成连接状态
        _channel.EnableRead();
        if (_connected_callback)
            _connected_callback(shared_from_this());
    }
    // 这个接口才是实际的释放接口
    void ReleaseInLoop()
    {
        // 修改连接状态，将其置为DISCONNECTED
        _statu = DISCONNECTED;
        // 移除连接的事件监控;
        _channel.Remove();
        // 关闭描述符
        _socket.Close();
        // 如果当前定时器队列中还有定时任务，则取消任务
        if (_loop->HasTimer(_conn_id))
            CanceleInactiveRelease();
        //调用关闭回调函数，避免先移除服务器管理的连接信息导致Connection被释放，因此先调用户的回调函数
        if (_closed_callback)
            _closed_callback(shared_from_this());
        if (_server_closed_callback)
            _server_closed_callback(shared_from_this());
    }
    //这个接口并不是实际的发送接口，而只是把数据放到了发送缓冲区，启动了可写事件监控
    //为什么要这么做？因为可写条件可能不就绪，即内核缓冲区的数据满了，写不进去了
    void SendInLoop(Buffer buf)
    {
        if (_statu == DISCONNECTED) // 如果状态已经关闭，则直接return，已经关闭则代表发送缓冲区数据为0
            return;
        _out_buffer.WriteBufferAndPush(buf);
        if (_channel.WriteAble() == false)
            _channel.EnableWrite();
    }
    // 这个关闭操作并非实际的连接释放操作，需要判断还有没有数据待处理，待发送
    void ShutdownInLoop()
    {
        _statu = DISCONNECTING; // 设置为半关闭状态
        if (_in_buffer.ReadAbleSize() > 0)
        {
            if (_message_callback)
                _message_callback(shared_from_this(), &_in_buffer);
        }
        //要么就是写入数据的时候出错关闭，要么就是没有待发送数据，直接关闭
        if (_out_buffer.ReadAbleSize() > 0)
        {
            if (_channel.WriteAble() == false)
            {
                _channel.EnableWrite();
            }
        }
        if (_out_buffer.ReadAbleSize() == 0)
        {
            Release();
        }
    }
    // 启动非活跃连接超时释放规则
    void EnableInactiveReleaseInLoop(int sec)
    {
        // 将判断标志位、_enable_inactive_erlease设置为true
        _enable_inactive_release = true;
        // 如果当前定时销毁任务已经存在，那就延迟刷新一下
        if (_loop->HasTimer(_conn_id))
            return _loop->TimerRefresh(_conn_id);
        // 如果不存在定时销毁任务，则新增
        _loop->TimerAdd(_conn_id, sec, std::bind(&Connection::Release, this));
    }
    // 取消非活跃连接超时释放规则
    void CancelInactiveReleaseInLoop()
    {
        _enable_inactive_release = false;
        if (_loop->HasTimer(_conn_id))
            _loop->TimerCancel(_conn_id);
    }
    // 切换协议/升级协议
    void UpgradeInLoop(const Any &context,
                       const ConnectedCallback &conn,
                       const MessageCallback &msg,
                       const ClosedCallback &closed,
                       const AnyEventCallback &event)
    {
        _context = context; //改变上下文
        _connected_callback = conn;
        _message_callback = msg;
        _closed_callback = closed;
        _event_callback = event;
    }

public:
    Connection(EventLoop *loop, uint64_t conn_id, int sockfd)
        : _conn_id(conn_id), _sockfd(sockfd), _enable_inactive_release(false), _loop(loop), _statu(CONNECTING),
          _socket(sockfd), _channel(loop, _sockfd)
    {
        _channel.SetReadCallback(std::bind(&Connection::HandleRead, this));
        _channel.SetWriteCallback(std::bind(&Connection::HandleWrite, this));
        _channel.SetCloseCallback(std::bind(&Connection::HandleClose, this));
        _channel.SetErrorCallback(std::bind(&Connection::HandleError, this));
        _channel.SetEventCallback(std::bind(&Connection::HandleEvent, this));
    }
    ~Connection()
    {
        DBG_LOG("RELEASE CONNEDCTION: %p", this);
    }
    // 获取管理的文件描述符
    int Fd()
    {
        return _sockfd;
    }
    // 获取连接ID
    int Id()
    {
        return _conn_id;
    }
    // 是否处于CONNECTED状态
    bool Connected()
    {
        return (_statu == CONNECTED);
    }
    // 设置上下文 -- 连接建立完成时进行调用
    void SetContext(const Any &context)
    {
        _context = context;
    }
    // 获取上下文，返回的是指针
    Any *GetContext()
    {
        return &_context;
    }
    void SetConnectedCallback(const ConnectedCallback &cb)
    {
        _connected_callback = cb;
    }
    void SetMessageCallback(const MessageCallback &cb)
    {
        _message_callback = cb;
    }
    void SetClosedCallback(const ClosedCallback &cb)
    {
        _closed_callback = cb;
    }
    void SetSvrClosedCallback(const ClosedCallback &cb)
    {
        _server_closed_callback = cb;
    }
    void SetAnyEventCallback(const AnyEventCallback &cb)
    {
        _event_callback = cb;
    }
    // 连接建立就绪后，进行channel回调设置，启动监控，调用_connected_callback
    void Established()
    {
        _loop->RunInLoop(std::bind(&Connection::EstablishedInLoop, this));
    }
    // 发送数据，将数据放到缓冲区，启动写事件监控
    void Send(const char *data, size_t len)
    {
        //为什么要重新创建一个临时变量？因为data可能是一个可能被释放的空间，我们将其压入任务队列等待被执行的过程中，空间可能被释放了
        Buffer buf;
        buf.WriteAndPush(data, len);
        _loop->RunInLoop(std::bind(&Connection::SendInLoop, this, std::move(buf)));
    }
    // 提供给组件使用者的关闭接口 -- 并不实际关闭，需要判断有没有数据待处理
    void Shutdown()
    {
        _loop->RunInLoop(std::bind(&Connection::ShutdownInLoop, this));
    }
    void Release()
    {
        _loop->QueueInLoop(std::bind(&Connection::ReleaseInLoop, this));
    }
    //启动非活跃销毁，并定义多长时间无通信就是非活跃，添加定时任务
    void EnableInactiveRelease(int sec)
    {
        _loop->RunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop, this, sec));
    }
    // 取消非活跃销毁
    void CanceleInactiveRelease()
    {
        _loop->RunInLoop(std::bind(&Connection::CancelInactiveReleaseInLoop, this));
    }
    //切换协议 -- 重置上下文以及阶段性处理函数
    void Upgrade(const Any &context, const ConnectedCallback &conn, const MessageCallback &msg, const ClosedCallback &closed, const AnyEventCallback &event)
    {
        _loop->RunInLoop(std::bind(&Connection::UpgradeInLoop, this, context, conn, msg, closed, event));
    }
};

class Acceptor
{
private:
    Socket _socket;   // 用于创建监听套接字
    EventLoop *_loop; // 用于对监听套接字进行事件监控
    Channel _channel; // 对于监听套接字进行事件管理

    using AcceptCallback = std::function<void(int)>;
    AcceptCallback _accept_callback; // 由Server模块提供的回调函数
private:
    // 监听套接字的读事件回调处理函数 -- 获取新连接，调用_accept_callback函数进行新连接处理
    void HandleRead()
    {
        int newfd = _socket.Accept();
        if (newfd < 0)
            return;
        if (_accept_callback)
            _accept_callback(newfd);
    }
    int CreateServer(uint64_t port)
    {
        bool ret = _socket.CreateServer(port);
        if (ret < 0)
            abort();
        return _socket.Fd();
    }

public:
    Acceptor(EventLoop *loop, int port)
        : _socket(CreateServer(port)),
          _loop(loop),
          _channel(loop, _socket.Fd())
    {
        _channel.SetReadCallback(std::bind(&Acceptor::HandleRead, this));
    }
    void SetAcceptCallback(const AcceptCallback &cb)
    {
        _accept_callback = cb;
    }
    void Listen()
    {
        _channel.EnableRead(); // 启动监听可读事件监控 --  会自动将自己挂到poller中
    }
};

class TcpServer
{
private:
    uint16_t _port;                                     // 服务器端口号。
    uint64_t _next_id;                                  // 这是Connection和定时任务公用的id  他是自动增长的，可以标记连接的唯一性。
    int _timeout;                                       // 非活跃链接超时时间
    bool _enable_inactive_release;                      // 是否启动非活跃连接超时销毁的判断标志
    EventLoop _baseloop;                                // 主线程EventLoop对象，负责监听事件的处理
    Acceptor _acceptor;                                 // 监听套接字的管理对象
    LoopThreadPool _pool;                               // 这是从属EventLoop线程池
    std::unordered_map<uint64_t, PtrConnection> _conns; // 保存管理所有对应的shared_ptr对象 -- 这里面的东西被删除，就意味着这个连接在某个不久的将来会被释放
    // 用户设置的回调函数 -- 未来要设置给Connection
    using ConnectedCallback = std::function<void(const PtrConnection &)>;
    using MessageCallback = std::function<void(const PtrConnection &, Buffer *)>;
    using ClosedCallback = std::function<void(const PtrConnection &)>;
    using AnyEventCallback = std::function<void(const PtrConnection &)>;
    using Functor = std::function<void()>;
    ConnectedCallback _connected_callback;
    MessageCallback _message_callback;
    ClosedCallback _closed_callback;
    AnyEventCallback _event_callback;

private:
    // 为新连接构建一个Connection
    void NewConnection(int fd)
    {
        _next_id++;
        PtrConnection conn(new Connection(_pool.NextLoop(), _next_id, fd));
        conn->SetMessageCallback(_message_callback);
        conn->SetClosedCallback(_closed_callback);
        conn->SetSvrClosedCallback(std::bind(&TcpServer::RemoveConnection, this, std::placeholders::_1));
        conn->SetConnectedCallback(_connected_callback);
        conn->SetAnyEventCallback(_event_callback);
        if (_enable_inactive_release)
            conn->EnableInactiveRelease(_timeout);
        conn->Established(); // 就绪初始化
        _conns.insert(std::make_pair(_next_id, conn));
    }
    void RemoveConnectionInLoop(const PtrConnection &conn)
    {
        int id = conn->Id();
        auto it = _conns.find(id);
        if (it != _conns.end())
        {
            _conns.erase(it);
        }
    }
    // 从管理Connection的_conns中移除连接信息 -- 因为对STL容器进行操作，所以需要考虑线程安全的问题
    void RemoveConnection(const PtrConnection &conn)
    {
        _baseloop.RunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop, this, conn));
    }
    void RunAfterInLoop(const Functor &task, int delay)
    {
        _next_id++;
        _baseloop.TimerAdd(_next_id, delay, task);
    }

public:
    TcpServer(int port)
        : _port(port), _next_id(0), _enable_inactive_release(false), _acceptor(&_baseloop, port), _pool(&_baseloop)
    {
        _acceptor.SetAcceptCallback(std::bind(&TcpServer::NewConnection, this, std::placeholders::_1));
        _acceptor.Listen();
    }
    // 设置从属线程数量
    void SetThreadCount(int count)
    {
        return _pool.SetThreadCount(count);
    }
    void SetConnectedCallback(const ConnectedCallback &cb)
    {
        _connected_callback = cb;
    }
    void SetMessageCallback(const MessageCallback &cb)
    {
        _message_callback = cb;
    }
    void SetClosedCallback(const ClosedCallback &cb)
    {
        _closed_callback = cb;
    }
    void SetAnyEventCallback(const AnyEventCallback &cb)
    {
        _event_callback = cb;
    }
    void EnableInactiveRelease(int timeout)
    {
        _timeout = timeout;
        _enable_inactive_release = true;
    }
    //用于添加一个定时任务 -- 提供给我们用户的
    void RunAter(const Functor &task, int delay)
    {
        _baseloop.RunInLoop(std::bind(&TcpServer::RunAfterInLoop, this, task, delay));
    }
    void Start()
    {
        _pool.Create();
        _baseloop.Start();
    }
};

void TimerWheel::TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerAddInLoop, this, id, delay, cb));
}
void TimerWheel::TimerRefresh(uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerRefreshInLoop, this, id));
}
void TimerWheel::TimerCancel(uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerCancelInLoop, this, id));
}

void Channel::Remove() //因为EventLoop还没有实现，为了测试Channel和Poller，先暂时直接用Poller里的接口进行操作
{
    return _loop->RemoveEvent(this);
}
void Channel::Update() //因为EventLoop还没有实现，为了测试Channel和Poller，先暂时直接用Poller里的接口进行操作
{
    return _loop->UpdateEvent(this);
}
class NetWork
{
public:
    NetWork()
    {
        DBG_LOG("SIGPIPE INIT");
        signal(SIGPIPE, SIG_IGN);
    }
};
static NetWork nw; //主要是调用该类的构造函数
